﻿Imports System
Imports System.Text
Imports System.Collections.Generic
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports WPFLOBMVVM
Imports BusinessEntityObjects
Imports BusinessLayer
Imports DataLayer
Imports Ocean.OceanFramework.MVVM
Imports Ocean.OceanFramework.CommonDialog
Imports System.Windows
Imports System.Windows.Input
'
<TestClass()> Public Class ApplicationUnitTests

#Region " Declarations "

    Private _objUnitTestResponder As ViewModelUIServiceUnitTestResponder
    Private _testContextInstance As TestContext

#End Region

#Region " Properties "

    '''<summary>
    '''Gets or sets the test context which provides
    '''information about and functionality for the current test run.
    '''</summary>
    Public Property TestContext() As TestContext
        Get
            Return _testContextInstance
        End Get
        Set(ByVal value As TestContext)
            _testContextInstance = value
        End Set
    End Property

#End Region

#Region " Test Initialization & Clean Up "

    '
    ' You can use the following additional attributes as you write your tests:
    '
    ' Use ClassInitialize to run code before running the first test in the class
    '<ClassInitialize()> Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)
    'End Sub
    '
    ' Use ClassCleanup to run code after all tests in a class have run
    ' <ClassCleanup()> Public Shared Sub MyClassCleanup()
    ' End Sub
    '
    ' Use TestInitialize to run code before running each test
    <TestInitialize()> _
    Public Sub MyTestInitialize()
        _objUnitTestResponder = New ViewModelUIServiceUnitTestResponder
        ViewModelUIService.SetViewModelUIServiceForUnitTesting(_objUnitTestResponder)
        AddHandler ViewModelUIService.Log, AddressOf Logger_Log
    End Sub

    ' Use TestCleanup to run code after each test has run
    <TestCleanup()> _
    Public Sub MyTestCleanup()
        RemoveHandler ViewModelUIService.Log, AddressOf Logger_Log
    End Sub

    '
#End Region

#Region " Test Methods "

    <TestMethod()> _
    Public Sub VerifyDatabaseConnection()

        Try
            Assert.IsTrue(DataLayer.ContactDAL.CreateInstance.Count > 0, "No records in database")

        Catch ex As Exception
            Assert.Fail("Connection to database failed, " & ex.ToString)
        End Try

    End Sub

    '
    <TestMethod(), _
     DeploymentItem("WPFLOBMVVM.exe")> _
    Public Sub TestApplicationMainWindowViewModel()

        Dim target As ApplicationMainWindowViewModel_Accessor = New ApplicationMainWindowViewModel_Accessor
        Assert.IsTrue(target.Forms.Count = 0, "Tab control has a pre-loaded form.")
        Assert.IsTrue(target.CanApplicationClose = True, "Application has invalid initial state, currently can't close.")
        'give background process time to get cranked up
        System.Threading.Thread.Sleep(2000)
        Assert.IsTrue(target._objTimeZoneLookupDictionary.ContainsKey("PST"), "Time zone dictionary missing PST")
        Assert.IsTrue(target._objTimeZoneLookupDictionary("PST") = "-0800", "PST time zone value wrong")

        If My.Computer.Network.IsAvailable Then
            Assert.IsTrue(target.Progress > 0, "Background thread is not running to load blog posts data from the web")
            Assert.IsTrue(target.LoadingActivityVisibility = Visibility.Visible, "Menu ProgressBar is not visible.")
        End If

        Assert.IsTrue(target.LogoVisibility = Visibility.Visible, "Logo is not visible when no forms are loaded.")

        Dim cmd As ICommand = target.LoadEditContactsAjaxComboBoxSelectionCommand
        Assert.IsTrue(cmd.CanExecute(Nothing) = True, "LoadEditContactsAjaxComboBoxSelectionCommand command can't execute.")
        cmd.Execute(Nothing)
        cmd = target.RecentBlogActivityCommand
        Assert.IsTrue(cmd.CanExecute(Nothing) = False, "Recent blog activity should not allow exectution.")
        cmd = target.RefreshActivityDataCommand

        If My.Computer.Network.IsAvailable Then
            Assert.IsTrue(cmd.CanExecute(Nothing) = False, "Refresh blog activity should not allow exectution.")
        End If

        Assert.IsTrue(target.Forms.Count = 1, "Failed to load LoadEditContactsAjaxComboBoxSelectionCommand in Tab Control.")
        Assert.IsTrue(target.LogoVisibility = Visibility.Collapsed, "Logo is not collapsed when forms are loaded.")
        Assert.IsTrue(target.CanApplicationClose = True, "Application has invalid initial state after loading LoadEditContactsAjaxComboBoxSelectionCommand, currently can't close.")

        Dim innerTarget As ClosableViewModelBase = target.Forms(0)
        cmd = innerTarget.RequestCloseCommand
        Assert.IsTrue(cmd.CanExecute(Nothing) = True, "LoadEditContactsAjaxComboBoxSelectionCommand, inner target request close command can't execute.")
        cmd.Execute(Nothing)
        Assert.IsTrue(target.Forms.Count = 0, "Inner target did not unload.")
        Assert.IsTrue(target.LogoVisibility = Visibility.Visible, "Logo is not visible after all forms are closed.")
    End Sub

    <TestMethod()> _
    Public Sub TestEditContactsAjaxComboBoxSelectionViewModel()

        Dim intTotalContacts As Integer = ContactBLL.CreateInstance.Count
        Dim target As New EditContactsAjaxComboBoxSelectionViewModel
        Dim strViewModel As String = "EditContactsViewModel"
        Assert.IsTrue(target.ViewModelFriendlyName = "WPF Disciples", "ViewFriendlyName is incorrect.")
        Assert.IsTrue(target.IsDirty = False, strViewModel & " has invalid initial state.  IsDirty was True.")
        Assert.IsTrue(Not String.IsNullOrEmpty(target.ContactViewModel.Contact.Error), strViewModel & " initial load of empty business object did not report invalid form, should have errors.")
        Assert.IsTrue(target.ContactViewModel.Contact.Id = 0, strViewModel & " invalid Id.  Id should be zero but was: " & target.ContactViewModel.Contact.Id.ToString)
        Assert.IsTrue(target.ContactViewModel.Contact.Item("FirstName").StartsWith("First Name can not be less than 1 character(s) long"), strViewModel & " FirstName property does not return the correct initial error message.")
        target.ContactViewModel.Contact.FirstName = "cool breeze"
        Assert.IsTrue(target.ContactViewModel.Contact.FirstName = "Cool Breeze", strViewModel & " case correction failed on FirstName.")
        Assert.IsTrue(target.IsDirty = True, strViewModel & " has invalid state after editing a field.  IsDirty was False.")
        target.ContactViewModel.Contact.LastName = "jones"
        target.ContactViewModel.Contact.NumberOfComputers = 10
        target.ContactViewModel.Contact.Birthday = #12/25/1958#
        Assert.IsTrue(String.IsNullOrEmpty(target.ContactViewModel.Contact.Error), strViewModel & " after populating all fields, form was still invalid.")

        Dim cmd As ICommand = target.SaveCommand
        cmd.Execute(Nothing)
        Assert.IsTrue(target.ContactViewModel.Contact.Id > 0, strViewModel & " Save failed.  Id should be greater than zero but was: " & target.ContactViewModel.Contact.Id.ToString)
        Assert.IsTrue(ContactBLL.CreateInstance.Count = intTotalContacts + 1, strViewModel & " after save, ContactSearchResults did not return the correct count, instead returned: " & ContactBLL.CreateInstance.Count.ToString)
        cmd = target.DeleteCommand
        _objUnitTestResponder.DialogResult = CustomDialogResult.No

        Dim intId As Integer = target.ContactViewModel.Contact.Id
        cmd.Execute(Nothing)
        Assert.IsTrue(target.ContactViewModel.Contact.Id = intId, strViewModel & " Delete should not have run because it was cancelled.  The Id after the attemped Delete should have matched the Id prior to the delete but does not.")
        Assert.IsTrue(ContactBLL.CreateInstance.Count = intTotalContacts + 1, strViewModel & " Delete should not have run because it was cancelled.  The ContactSearchResults did not return the correct count.")
        _objUnitTestResponder.DialogResult = CustomDialogResult.Yes
        cmd.Execute(Nothing)
        Assert.IsTrue(target.ContactViewModel.Contact.Id = 0, strViewModel & " Delete failed.  Id should be zero but was: " & target.ContactViewModel.Contact.Id.ToString)
        Assert.IsTrue(ContactBLL.CreateInstance.Count = intTotalContacts, strViewModel & " after delete, ContactSearchResults did not return the correct count, instead returned: " & ContactBLL.CreateInstance.Count.ToString)

        Dim objSearchResults As List(Of ContactSearchResult) = ContactBLL.CreateInstance.SearchByLastName("s")

        If objSearchResults IsNot Nothing AndAlso objSearchResults.Count > 1 Then

            Dim strBlogURL As String = "http://karlshifflett.wordpress.com"
            target.Select(objSearchResults(0).Id)
            Assert.IsTrue(target.ContactViewModel.Contact.Id = objSearchResults(0).Id, "Selected failed to load Contact, Id: " & objSearchResults(0).Id.ToString)
            Assert.IsTrue(target.IsDirty = False, "Contact was dirty after selection.")
            Assert.IsTrue(target.ContactViewModel.Contact.ActiveRuleSet = "Update", "After selection, Contact ActiveRuleSet was not Update.  Instead was: " & target.ContactViewModel.Contact.ActiveRuleSet)
            target.ContactViewModel.Contact.BlogURL = strBlogURL
            Assert.IsTrue(target.IsDirty = True, "Contact was not dirty after changing field value.")
            cmd = target.SaveCommand
            cmd.Execute(Nothing)
            target.Select(objSearchResults(1).Id)
            target.Select(objSearchResults(0).Id)
            Assert.IsTrue(target.ContactViewModel.Contact.BlogURL = strBlogURL, "Contact blog url was not saved correctly to the database.")
            target.ContactViewModel.Contact.Birthday = #12/25/1960#
            cmd = target.RequestCloseCommand
            Assert.IsTrue(cmd.CanExecute(Nothing) = True, "RequestCloseCommand command can't execute.")
            _objUnitTestResponder.DialogResult = CustomDialogResult.Cancel
            Assert.IsTrue(target.VerifyDataBeforeClosing() = False, "VerifyDataBeforeClosing failed.  Cancelled was the programmed response, should hve returned false.")
            _objUnitTestResponder.DialogResult = CustomDialogResult.No
            Assert.IsTrue(target.VerifyDataBeforeClosing() = True, "VerifyDataBeforeClosing failed.  No was the programmed response, should hve returned true.")
            target.Select(objSearchResults(0).Id)
            target.ContactViewModel.Contact.Birthday = #12/25/1960#
            _objUnitTestResponder.DialogResult = CustomDialogResult.Yes
            Assert.IsTrue(target.VerifyDataBeforeClosing() = True, "VerifyDataBeforeClosing failed.  Yes was the programmed response, should hve returned true.")
            target.Select(objSearchResults(1).Id)
            target.Select(objSearchResults(0).Id)
            Assert.IsTrue(target.ContactViewModel.Contact.Birthday.HasValue AndAlso target.ContactViewModel.Contact.Birthday.Value = #12/25/1960#, "Contact Birthday not saved correctly when form closed.")

        Else
            Assert.Fail("Search by last name, searching for 's' failed.  Test requires at least two records be returned.")
        End If

    End Sub

    <TestMethod()> _
    Public Sub TestContactValidation()

        Dim target As Contact = ContactBLL.CreateInstance.Create
        Assert.IsTrue(target.IsDirty = False, "Contact has invalid initial state.  IsDirty was True.")
        With target
            .ActiveRuleSet = "Update"
            .Birthday = Nothing
            Assert.IsTrue(String.IsNullOrEmpty(.Item("Birthday")), "Birthday null check failed.  Birthday should allow null date.")
            .Birthday = Now.AddDays(1)
            Assert.IsTrue(Not String.IsNullOrEmpty(.Item("Birthday")), "Birthday rule date after current day failed.  Birthday must be before today.")
            .Birthday = Now.AddDays(-2)
            Assert.IsTrue(target.IsDirty = True, "Contact IsDirty is invalid, should be True.")
            .BlogURL = String.Empty
            Assert.IsTrue(String.IsNullOrEmpty(.Item("BlogURL")), "BlogURL empty field check failed.  BlogURL should allow empty string.")
            .BlogURL = "hello"
            Assert.IsTrue(Not String.IsNullOrEmpty(.Item("BlogURL")), "BlogURL regular expression check failed.  BlogURL should require a valid URL but allowed a malformed URL to be entered.")
            .BlogURL = "http://KarlShifflett.wordpress.com"
            Assert.IsTrue(String.IsNullOrEmpty(.Item("BlogURL")), "BlogURL regular expression check failed.  BlogURL should allow a valid URL but did not.")
            Assert.IsTrue(String.Compare(target.BlogURL, "http://karlshifflett.wordpress.com") = 0, "BlogURL lower case ruled failed.  BlogURL should be converted to lower case automatically.")
            .BlogURL = New String("x"c, 150)
            Assert.IsTrue(Not String.IsNullOrEmpty(.Item("BlogURL")), "BlogURL length check failed.  BlogURL is limited to 100 characters but the rule was not enforced.")
            .BlogURL = String.Empty
            .FeedURL = String.Empty
            Assert.IsTrue(String.IsNullOrEmpty(.Item("FeedURL")), "FeedURL empty field check failed.  FeedURL should allow empty string.")
            .FeedURL = "hello"
            Assert.IsTrue(Not String.IsNullOrEmpty(.Item("FeedURL")), "FeedURL regular expression check failed.  FeedURL should require a valid URL but allowed a malformed URL to be entered.")
            .FeedURL = "http://KarlShifflett.wordpress.com/feed/"
            Assert.IsTrue(String.IsNullOrEmpty(.Item("FeedURL")), "FeedURL regular expression check failed.  FeedURL should allow a valid URL but did not.")
            Assert.IsTrue(String.Compare(target.FeedURL, "http://KarlShifflett.wordpress.com/feed/") = 0, "FeedURL was changed to lower case but should not have been.")
            .FeedURL = New String("x"c, 150)
            Assert.IsTrue(Not String.IsNullOrEmpty(.Item("FeedURL")), "FeedURL length check failed.  FeedURL is limited to 100 characters but the rule was not enforced.")
            .FeedURL = String.Empty
            .FirstName = "karl"
            Assert.IsTrue(String.Compare(.FirstName, "Karl") = 0, "First name case correction rule failed.")
            .LastName = "shifflett"
            Assert.IsTrue(String.Compare(.LastName, "Shifflett") = 0, "Last name case correction rule failed.")
            .Id = 20
            .NumberOfComputers = 15
            Assert.IsTrue(String.IsNullOrEmpty(.Error), "Contact should be valid but is not, returned errors were: " & .Error)
            Assert.IsTrue(.IsValid = True, "Contact should be valid but is not.")
            Assert.IsTrue(.HasBeenValidated = True, "Contact HasBeenValidated was not True.")
            .NumberOfComputers = -15
            Assert.IsTrue(Not String.IsNullOrEmpty(.Error), "Contact should be invalid after setting number of computers to -15 but is valid.")
            Assert.IsTrue(.IsValid = False, "Contact should be not be valid but is.")
            Assert.IsTrue(.HasBeenValidated = False, "Contact HasBeenValidated was True but should be false.")
        End With
    End Sub

#End Region

#Region " Logger Methods "

    Private Sub Logger_Log(ByVal sender As Object, ByVal e As LogEventArgs)
        My.Computer.FileSystem.WriteAllText("Logger.txt", "------------------------------------------------------------------------------------" & vbCrLf, True)
        My.Computer.FileSystem.WriteAllText("Logger.txt", "Test Name: " & _testContextInstance.TestName & vbCrLf, True)

        If e.Exception IsNot Nothing Then
            My.Computer.FileSystem.WriteAllText("Logger.txt", e.InstructionHeading & vbCrLf, True)
            My.Computer.FileSystem.WriteAllText("Logger.txt", e.InstructionText & vbCrLf, True)
            My.Computer.FileSystem.WriteAllText("Logger.txt", e.Exception.ToString & vbCrLf, True)

            Dim ex As Exception = e.Exception.InnerException

            Do While ex IsNot Nothing
                My.Computer.FileSystem.WriteAllText("Logger.txt", ex.ToString & vbCrLf, True)
                ex = ex.InnerException
            Loop

        Else
            My.Computer.FileSystem.WriteAllText("Logger.txt", e.InstructionHeading & vbCrLf, True)
            My.Computer.FileSystem.WriteAllText("Logger.txt", e.InstructionText & vbCrLf, True)
            My.Computer.FileSystem.WriteAllText("Logger.txt", e.CustomDialogResult.ToString & vbCrLf, True)
        End If

        My.Computer.FileSystem.WriteAllText("Logger.txt", "" & vbCrLf, True)
        My.Computer.FileSystem.WriteAllText("Logger.txt", "" & vbCrLf, True)
    End Sub

#End Region

End Class
